﻿using System;
using System.Collections.Generic;
using Protocol.Dto.Fight;

namespace Protocol.Constant
{
    /// <summary>
    /// 出牌类型
    /// </summary>
    public static class CardType
    {
        public const int NONE = 0;
        public const int SINGLE = 1;
        public const int DOUBLE = 2;
        public const int STRAIGHT = 3;
        public const int DOUBLE_STRAIGHT = 4;
        public const int TRIPLE_STRAIGHT = 5;
        public const int THREE = 6;
        public const int THREE_ONE = 7;
        public const int THREE_TWO = 8;
        public const int BOOM = 9;
        public const int JOKER_BOOM = 10;


        /// <summary>
        /// 是否是单牌
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsSingle(List<CardDto> cardDtos)
        {
            return cardDtos.Count == 1;
        }

        /// <summary>
        /// 是否是双牌
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsDouble(List<CardDto> cardDtos)
        {
            if (cardDtos.Count == 2)
            {
                if (cardDtos[0].Weight == cardDtos[1].Weight)
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 是否是顺子
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsStraight(List<CardDto> cardDtos)
        {
            if (cardDtos.Count < 5 || cardDtos.Count > 12)
            {
                return false;
            }


            for (int i = 0; i < cardDtos.Count - 1; i++)
            {
                int tempWight = cardDtos[i].Weight;

                if (cardDtos[i + 1].Weight - tempWight != 1)
                {
                    return false;
                }

                // 不能超过A
                if (tempWight > CardWeight.ONE || cardDtos[i + 1].Weight > CardWeight.ONE)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 是否是双顺
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsDoubleStraight(List<CardDto> cardDtos)
        {
            if (cardDtos.Count < 6 || cardDtos.Count % 2 != 0)
            {
                return false;
            }

            for (int i = 0; i < cardDtos.Count - 2; i++)
            {
                if (cardDtos[i].Weight != cardDtos[i + 1].Weight)
                {
                    return false;
                }

                if (cardDtos[i + 2].Weight - cardDtos[i].Weight != 1)
                {
                    return false;
                }

                // 不能超过A
                if (cardDtos[i].Weight > CardWeight.ONE || cardDtos[i + 2].Weight > CardWeight.ONE)
                {
                    return false;
                }
            }

            return true;
        }

        /// <summary>
        /// 是否是飞机
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsTripleStraight(List<CardDto> cardDtos)
        {
            if (cardDtos.Count < 6 || cardDtos.Count % 3 != 0)
            {
                return false;
            }

            for (int i = 0; i < cardDtos.Count - 3; i++)
            {
                if (cardDtos[i].Weight != cardDtos[i + 1].Weight)
                {
                    return false;
                }

                if (cardDtos[i + 2].Weight != cardDtos[i + 1].Weight)
                {
                    return false;
                }

                if (cardDtos[i].Weight != cardDtos[i + 2].Weight)
                {
                    return false;
                }

                if (cardDtos[i + 3].Weight - cardDtos[i].Weight != 1)
                {
                    return false;
                }

                // 不能超过A
                if (cardDtos[i].Weight > CardWeight.ONE || cardDtos[i + 3].Weight > CardWeight.ONE)
                {
                    return false;
                }
            }

            return true;
        }


        /// <summary>
        /// 是否是三不带
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsThree(List<CardDto> cardDtos)
        {
            if (cardDtos.Count != 3)
            {
                return false;
            }

            if (cardDtos[0].Weight != cardDtos[1].Weight)
            {
                return false;
            }

            if (cardDtos[2].Weight != cardDtos[1].Weight)
            {
                return false;
            }

            if (cardDtos[0].Weight != cardDtos[2].Weight)
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 是不是三带一
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsThreeAndOne(List<CardDto> cardDtos)
        {
            if (cardDtos.Count != 4)
            {
                return false;
            }

            if (cardDtos[0].Weight == cardDtos[1].Weight && cardDtos[1].Weight == cardDtos[2].Weight)
            {
                return true;
            }

            if (cardDtos[1].Weight == cardDtos[2].Weight && cardDtos[2].Weight == cardDtos[3].Weight)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 是否是三代二
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        public static bool IsThreeAndTwo(List<CardDto> cardDtos)
        {
            if (cardDtos.Count != 5)
            {
                return false;
            }

            if (cardDtos[0].Weight == cardDtos[1].Weight && cardDtos[1].Weight == cardDtos[2].Weight)
            {
                if (cardDtos[3].Weight == cardDtos[4].Weight)
                {
                    return true;
                }
            }

            if (cardDtos[2].Weight == cardDtos[3].Weight && cardDtos[3].Weight == cardDtos[4].Weight)
            {
                if (cardDtos[0].Weight == cardDtos[1].Weight)
                {
                    return true;
                }
            }

            return false;
        }


        /// <summary>
        /// 判断是不是炸弹
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsBoom(List<CardDto> cardDtos)
        {
            if (cardDtos.Count != 4)
            {
                return false;
            }

            // 4张牌必须一样weight
            for (int i = 0; i < cardDtos.Count - 1; i++)
            {
                if (cardDtos[i].Weight != cardDtos[i + 1].Weight)
                {
                    return false;
                }
            }

            return true;
        }


        /// <summary>
        /// 是不是王炸弹
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        private static bool IsJokerBoom(List<CardDto> cardDtos)
        {
            if (cardDtos.Count != 2)
            {
                return false;
            }

            if (cardDtos[0].Weight == CardWeight.SJOKER && cardDtos[1].Weight == CardWeight.LJOKER)
            {
                return true;
            }

            if (cardDtos[0].Weight == CardWeight.SJOKER && cardDtos[1].Weight == CardWeight.LJOKER)
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判断是否能出牌
        /// </summary>
        /// <param name="cardDtos"></param>
        /// <returns></returns>
        public static int GetCardType(List<CardDto> cardDtos)
        {
            int cardType = NONE;

            switch (cardDtos.Count)
            {
                case 1:
                    if (IsSingle(cardDtos))
                    {
                        cardType = SINGLE;
                    }

                    break;
                case 2:
                    if (IsDouble(cardDtos))
                    {
                        cardType = DOUBLE;
                    }
                    else if (IsJokerBoom(cardDtos))
                    {
                        cardType = JOKER_BOOM;
                    }

                    break;
                case 3:
                    if (IsThree(cardDtos))
                    {
                        cardType = THREE;
                    }

                    break;
                case 4:
                    if (IsBoom(cardDtos))
                    {
                        cardType = BOOM;
                    }
                    else if (IsThreeAndOne(cardDtos))
                    {
                        cardType = THREE_ONE;
                    }

                    break;

                case 5:
                case 6:
                case 12:

                    if (IsStraight(cardDtos))
                    {
                        cardType = STRAIGHT;
                    }
                    else if (IsDoubleStraight(cardDtos))
                    {
                        cardType = DOUBLE_STRAIGHT;
                    }
                    else if (IsTripleStraight(cardDtos))
                    {
                        cardType = TRIPLE_STRAIGHT;
                    }

                    break;
                case 7:
                    if (IsStraight(cardDtos))
                    {
                        cardType = STRAIGHT;
                    }

                    break;
                case 8:
                case 10:
                    if (IsStraight(cardDtos))
                    {
                        cardType = STRAIGHT;
                    }
                    else if (IsDoubleStraight(cardDtos))
                    {
                        cardType = DOUBLE_STRAIGHT;
                    }

                    break;
                case 9:
                    if (IsStraight(cardDtos))
                    {
                        cardType = STRAIGHT;
                    }
                    else if (IsTripleStraight(cardDtos))
                    {
                        cardType = TRIPLE_STRAIGHT;
                    }

                    break;
                case 11:
                    if (IsStraight(cardDtos))
                    {
                        cardType = STRAIGHT;
                    }

                    break;
                case 13:
                    break;
                case 14:
                case 16:
                case 20:
                    if (IsDoubleStraight(cardDtos))
                    {
                        cardType = DOUBLE_STRAIGHT;
                    }

                    break;
                case 15:
                    if (IsTripleStraight(cardDtos))
                    {
                        cardType = TRIPLE_STRAIGHT;
                    }

                    break;
                case 17:
                    break;
                case 18:
                    if (IsDoubleStraight(cardDtos))
                    {
                        cardType = DOUBLE_STRAIGHT;
                    }
                    else if (IsTripleStraight(cardDtos))
                    {
                        cardType = TRIPLE_STRAIGHT;
                    }

                    break;
                case 19:
                    break;
                default:
                    throw new Exception("逻辑错误");
            }

            return cardType;
        }
    }
}